#include "xmlhandler.h"

XMLHandler::XMLHandler(XMLInterface *x) :
    QXmlDefaultHandler()
{
    xml = x;
    inPropName = inPoint = inLat = inLon = inAlt = inRad = inAudMain = inAud = inVid = inPic = false;
    pointType = PROP_POINT;
    latitude = longitude = altitude = radius = 0.0;
    propCoords.resize(4);
}

bool XMLHandler::startElement(const QString &namespaceURI,
                              const QString &localName,
                              const QString &qName,
                              const QXmlAttributes &atts)
{
    if (qName.toLower() == "prop")
    {
        propName = audMain = audMainScript = audMainScriptFile = "";
        aud.clear();
        vid.clear();
        pic.clear();
        pointType = PROP_POINT;
        propCoords.clear();
        propCoords.resize(4);
        latitude = longitude = altitude = radius = 0.0;
    }
    else if (qName.toLower() == "propname")
    {
        inPropName = true;
    }
    else if (qName.toLower() == "minimap")
    {
        propName = audMain = audMainScript = audMainScriptFile = "";
        aud.clear();
        vid.clear();
        pic.clear();
        propCoords.clear();
        propCoords.resize(2);
        int index = atts.index("img");
        pic.push_back(atts.value(index).trimmed());
    }
    else if (qName.toLower() == "point")
    {
        int index = atts.index("type");
        if (index != -1)
        {
            if (atts.value(index).trimmed().toLower() == "topleft")
            {
                pointType = MINIMAP_TOP_POINT;
            }
            else if (atts.value(index).trimmed().toLower() == "lowright")
            {
                pointType = MINIMAP_LOW_POINT;
            }
            else
            {
                pointType = PROP_POINT;
            }
        }
        else
        {
            pointType = PROP_POINT;
        }
    }
    else if (qName.toLower() == "lat")
    {
        inLat = true;
    }
    else if (qName.toLower() == "lon")
    {
        inLon = true;
    }
    else if (qName.toLower() == "alt")
    {
        inAlt = true;
    }
    else if (qName.toLower() == "rad")
    {
        inRad = true;
    }
    else if (qName.toLower() == "audiomain")
    {
        inAudMain = true;
        int index = atts.index("script");
        if (index != -1)
        {
            audMainScriptFile = atts.value(index).trimmed();
        }
    }
    else if (qName.toLower() == "aud")
    {
        inAud = true;
    }
    else if (qName.toLower() == "vid")
    {
        inVid = true;
    }
    else if (qName.toLower() == "pic")
    {
        inPic = true;
    }
    return true;
}

bool XMLHandler::characters(const QString &ch)
{
    if (inPropName)
    {
        propName = ch.trimmed();
    }
    else if (inLat)
    {
        bool ok;
        latitude = ch.toDouble(&ok);
        if (!ok)
        {
            // TODO: handle error
        }
    }
    else if (inLon)
    {
        bool ok;
        longitude = ch.toDouble(&ok);
        if (!ok)
        {
            // TODO: handle error
        }
    }
    else if (inAlt)
    {
        bool ok;
        altitude = ch.toDouble(&ok);
        if (!ok)
        {
            // TODO: handle error
        }
    }
    else if (inRad)
    {
        bool ok;
        radius = ch.toDouble(&ok);
        if (!ok)
        {
            // TODO: handle error
        }
    }
    else if (inAudMain)
    {
        audMain = ch.trimmed();
    }
    else if (inAud)
    {
        aud.push_back(ch.trimmed());
    }
    else if (inVid)
    {
        vid.push_back(ch.trimmed());
    }
    else if (inPic)
    {
        pic.push_back(ch.trimmed());
    }
    return true;
}

bool XMLHandler::endElement(const QString &namespaceURI,
                            const QString &localName,
                            const QString &qName)
{
    if (qName.toLower() == "minimap")
    {
        tmpProp = new PropData("Minimap",
                               propCoords,
                               audMain,
                               audMainScript,
                               audMainScriptFile,
                               aud,
                               vid,
                               pic);
        xml->setMinimapFromXML(tmpProp);
    }
    else if (qName.toLower() == "prop")
    {
        tmpProp = new PropData(propName,
                               propCoords,
                               audMain,
                               audMainScript,
                               audMainScriptFile,
                               aud,
                               vid,
                               pic);
        xml->addPropFromXML(tmpProp);
    }
    else if (qName.toLower() == "propname")
    {
        inPropName = false;
    }
    else if (qName.toLower() == "point")
    {
        Coordinate c;
        c.latitude = latitude;
        c.longitude = longitude;
        c.altitude = altitude;
        c.radius = radius;
        if (pointType == MINIMAP_TOP_POINT)
        {
            propCoords[0] = c;
        }
        else if (pointType == MINIMAP_LOW_POINT)
        {
            propCoords[1] = c;
        }
        else
        {
            propCoords[0] = c;
        }
    }
    else if (qName.toLower() == "lat")
    {
        inLat = false;
    }
    else if (qName.toLower() == "lon")
    {
        inLon = false;
    }
    else if (qName.toLower() == "alt")
    {
        inAlt = false;
    }
    else if (qName.toLower() == "rad")
    {
        inRad = false;
    }
    else if (qName.toLower() == "audiomain")
    {
        inAudMain = false;
    }
    else if (qName.toLower() == "aud")
    {
        inAud = false;
    }
    else if (qName.toLower() == "vid")
    {
        inVid = false;
    }
    else if (qName.toLower() == "pic")
    {
        inPic = false;
    }
    return true;
}

bool XMLHandler::fatalError(const QXmlParseException &exception)
{
    qDebug() << "error line: " << exception.lineNumber() << "\nm: " << exception.message();
    return false;
}
